home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 1 (Walnut Creek)
/
Aminet - June 1993 [Walnut Creek].iso
/
usenet
/
sources
/
volume89
/
editors
/
stevie36.5
< prev
next >
Wrap
Internet Message Format
|
1989-05-12
|
56KB
Path: xanth!indri!ames!amdcad!sun!swap!page
From: page%swap@Sun.COM (Bob Page)
Newsgroups: comp.sources.amiga
Subject: v89i134: stevie - vi editor clone v3.6, Part05/06
Message-ID: <104421@sun.Eng.Sun.COM>
Date: 12 May 89 03:07:23 GMT
Sender: news@sun.Eng.Sun.COM
Lines: 2069
Approved: page@sun.com
Submitted-by: grwalter@watmath.waterloo.edu (Fred Walter)
Posting-number: Volume 89, Issue 134
Archive-name: editors/stevie36.5
# This is a shell archive.
# Remove anything above and including the cut line.
# Then run the rest of the file through 'sh'.
# Unpacked files will be owned by you and have default permissions.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar: SHell ARchive
# Run the following text through 'sh' to create:
# regexp.cat.uu
# regexp.h
# regmagic.h
# regsub.c
# s_io.c
# screen.c
# search.c
# This is archive 5 of a 6-part kit.
# This archive created: Thu May 11 19:41:28 1989
echo "extracting regexp.cat.uu"
sed 's/^X//' << \SHAR_EOF > regexp.cat.uu
X
Xbegin 644 regexp.cat
XM"@H*"E)%1T584"@S*2`@("`@("`@("`@("`@("!,:6)R87)Y($9U;F-T:6]NR
XM<R`@("`@("`@("`@("`@(%)%1T584"@S*0H*"@I."$Y!"$%-"$U%"$4*("`@6
XM("!R96=C;VUP+"!R96=E>&5C+"!R96=S=6(L(')E9V5R<F]R("T@<F5G=6QA1
XM<B!E>'!R97-S:6]N"B`@("`@:&%N9&QE<@H*4PA360A93@A.3PA/4`A04PA3&
XM20A)4PA3"B`@("`@(P@C:0AI;@AN8PAC;`AL=0AU9`AD90AE(#P(/'((<F4(Y
XM96<(9V4(97@(>'`(<"X(+F@(:#X(/@H*("`@("!R"')E"&5G"&=E"&5X"'APO
XM"'`@*@@J<@AR90AE9PAG8PAC;PAO;0AM<`AP*`@H90AE>`AX<`AP*0@I"B`@T
XM("`@8PAC:`AH80AA<@AR("H(*F4(97@(>'`(<#L(.PH*("`@("!I"&EN"&YT.
XM"'0@<@AR90AE9PAG90AE>`AX90AE8PAC*`@H<`AP<@AR;PAO9PAG+`@L(',(]
XM<W0(='((<FD(:6X(;F<(9RD(*0H@("`@('((<F4(96<(9V4(97@(>'`(<"`JW
XM""IP"'!R"')O"&]G"&<["#L*("`@("!C"&-H"&AA"&%R"'(@*@@J<PAS=`AT@
XM<@AR:0AI;@AN9PAG.P@["@H@("`@('((<F4(96<(9W,(<W4(=6((8B@(*'`("
XM<'((<F\(;V<(9RP(+"!S"'-O"&]U"'5R"')C"&-E"&4L""P@9`AD90AE<PASZ
XM=`AT*0@I"B`@("`@<@AR90AE9PAG90AE>`AX<`AP("H(*G`(<'((<F\(;V<(?
XM9SL(.PH@("`@(&,(8V@(:&$(87((<B`J""IS"'-O"&]U"'5R"')C"&-E"&4[T
XM"#L*("`@("!C"&-H"&AA"&%R"'(@*@@J9`AD90AE<PAS=`AT.P@["@H@("`@7
XM('((<F4(96<(9V4(97((<G((<F\(;W((<B@(*&T(;7,(<V<(9RD(*0H@("`@2
XM(&,(8V@(:&$(87((<B`J""IM"&US"'-G"&<["#L*"D0(1$4(15,(4T,(0U((H
XM4DD(25`(4%0(5$D(24\(3TX(3@H@("`@(%1H97-E(&9U;F-T:6]N<R!I;7!L6
XM96UE;G0*("`@("!?"&5?"&=?"')?"&5?"'`H,2DM<W1Y;&4*("`@("!R96=U6
XM;&%R(&5X<')E<W-I;VYS(&%N9"!S=7!P;W)T:6YG(&9A8VEL:71I97,N"@H@/
XM("`@(%\(4E\(95\(9U\(8U\(;U\(;5\(<`H@("`@(&-O;7!I;&5S(&$@<F5G#
XM=6QA<B!E>'!R97-S:6]N(&EN=&\@82!S=')U8W1U<F4@;V8@='EP90H@("`@Q
XM(%\(<E\(95\(9U\(95\(>%\(<"P*("`@("!A;F0@<F5T=7)N<R!A('!O:6YT<
XM97(@=&\@:70N"B`@("`@5&AE('-P86-E(&AA<R!B965N(&%L;&]C871E9"!UP
XM<VEN9PH@("`@(%\(;5\(85\(;%\(;%\(;U\(8R@S*0H@("`@(&%N9"!M87D@E
XM8F4@<F5L96%S960@8GD*("`@("!?"&9?"')?"&5?"&4N"@H@("`@(%\(4E\(1
XM95\(9U\(95\(>%\(95\(8PH@("`@(&UA=&-H97,@82!.54PM=&5R;6EN871E)
XM9"!?"'-?"'1?"')?"&E?"&Y?"&<@86=A:6YS="!T:&4@8V]M<&EL960@<F5GX
XM=6QA<B!E>'!R97-S:6]N"B`@("`@:6X@7PAP7PAR7PAO7PAG+@H@("`@($ETN
XM(')E='5R;G,@,2!F;W(@<W5C8V5S<R!A;F0@,"!F;W(@9F%I;'5R92P@86YD5
XM(&%D:G5S=',@=&AE(&-O;G1E;G1S(&]F"B`@("`@7PAP7PAR7PAO7PAG)W,@Z
XM7PAS7PAT7PAA7PAR7PAT7PAP(&%N9"!?"&5?"&Y?"&1?"'`@*'-E92!B96QO%
XM=RD@86-C;W)D:6YG;'DN"@H@("`@(%1H92!M96UB97)S(&]F(&$*("`@("!?<
XM"')?"&5?"&=?"&5?"'A?"'`*("`@("!S=')U8W1U<F4@:6YC;'5D92!A="!LV
XM96%S="!T:&4@9F]L;&]W:6YG("AN;W0@;F5C97-S87)I;'D@:6X@;W)D97(IV
XM.@H*("`@("`@("`@(&-H87(@*G-T87)T<%M.4U5"15A073L*("`@("`@("`@6
XM(&-H87(@*F5N9'!;3E-50D584%T["@H@("`@('=H97)E"B`@("`@7PA.7PA3O
XM7PA57PA"7PA%7PA87PA0"B`@("`@:7,@9&5F:6YE9"`H87,@,3`I(&EN('1HU
XM92!H96%D97(@9FEL92X*"@H*1F]R;6%T=&5D(#@X+S$R+S,P("`@("`@("`@^
XM("`@;&]C86P@("`@("`@("`@("`@("`@("`@("`@("`@("`@(#$*#`H*"@I2,
XM14=%6%`H,RD@("`@("`@("`@("`@("`@3&EB<F%R>2!&=6YC=&EO;G,@("`@K
XM("`@("`@("`@("!214=%6%`H,RD*"@H*("`@("!/;F-E(&$@<W5C8V5S<V9UQ
XM;"!?"')?"&5?"&=?"&5?"'A?"&5?"&,@:&%S(&)E96X@9&]N92!U<VEN9R!TV
XM:&4@7PAR7PAE7PAG7PAE7PAX7PAP+`H@("`@(&5A8V@@7PAS7PAT7PAA7PAR_
XM7PAT7PAP+5\(95\(;E\(9%\(<"!P86ER(&1E<V-R:6)E<R!O;F4@<W5B<W1RG
XM:6YG"B`@("`@=VET:&EN('1H92!?"'-?"'1?"')?"&E?"&Y?"&<L"B`@("`@3
XM=VET:"!T:&4@7PAS7PAT7PAA7PAR7PAT7PAP('!O:6YT:6YG('1O('1H92!FW
XM:7)S="!C:&%R86-T97(@;V8@=&AE('-U8G-T<FEN9R!A;F0*("`@("!T:&4@$
XM7PAE7PAN7PAD7PAP('!O:6YT:6YG('1O('1H92!F:7)S="!C:&%R86-T97(@D
XM9F]L;&]W:6YG('1H92!S=6)S=')I;F<N"B`@("`@5&AE(#!T:"!S=6)S=')I$
XM;F<@:7,@=&AE('-U8G-T<FEN9R!O9B!?"'-?"'1?"')?"&E?"&Y?"&<@=&AAF
XM="!M871C:&5D('1H92!W:&]L90H@("`@(')E9W5L87(@97AP<F5S<VEO;BX*.
XM("`@("!4:&4@;W1H97)S(&%R92!T:&]S92!S=6)S=')I;F=S('1H870@;6%TX
XM8VAE9"!P87)E;G1H97-I>F5D(&5X<')E<W-I;VYS"B`@("`@=VET:&EN('1H&
XM92!R96=U;&%R(&5X<')E<W-I;VXL('=I=&@@<&%R96YT:&5S:7IE9"!E>'!RD
XM97-S:6]N<R!N=6UB97)E9`H@("`@(&EN(&QE9G0M=&\M<FEG:'0@;W)D97(@Y
XM;V8@=&AE:7(@;W!E;FEN9R!P87)E;G1H97-E<RX*"B`@("`@7PA27PAE7PAG8
XM7PAS7PAU7PAB"B`@("`@8V]P:65S(%\(<U\(;U\(=5\(<E\(8U\(92!T;R!?)
XM"&1?"&5?"'-?"'0L(&UA:VEN9R!S=6)S=&ET=71I;VYS(&%C8V]R9&EN9R!T>
XM;R!T:&4*("`@("!M;W-T(')E8V5N="!?"')?"&5?"&=?"&5?"'A?"&5?"&,@2
XM<&5R9F]R;65D('5S:6YG(%\(<%\(<E\(;U\(9RX*("`@("!%86-H(&EN<W1A&
XM;F-E(&]F(&`F)R!I;B!?"'-?"&]?"'5?"')?"&-?"&4@:7,@<F5P;&%C960@&
XM8GD@=&AE('-U8G-T<FEN9PH@("`@(&EN9&EC871E9"!B>2!?"'-?"'1?"&%?#
XM"')?"'1?"'!;7P@P72!A;F0*("`@("!?"&5?"&Y?"&1?"'!;7P@P72X*("`@B
XM("!%86-H(&EN<W1A;F-E(&]F(&!<7PAN)RP@=VAE<F4@7PAN(&ES(&$@9&EG@
XM:70L(&ES(')E<&QA8V5D(&)Y"B`@("`@=&AE('-U8G-T<FEN9R!I;F1I8V%T(
XM960@8GD*("`@("!?"'-?"'1?"&%?"')?"'1?"'!;7PAN72!A;F0*("`@("!??
XM"&5?"&Y?"&1?"'!;7PAN72X*("`@("!4;R!G970@82!L:71E<F%L(&`F)R!O6
XM<B!@7%\(;B<@:6YT;R!?"&1?"&5?"'-?"'0L('!R969I>"!I="!W:71H(&!<?
XM)SL*("`@("!T;R!G970@82!L:71E<F%L(&!<)R!P<F5C961I;F<@8"8G(&]R_
XM(&!<7PAN)RP@<')E9FEX(&ET('=I=&@*("`@("!A;F]T:&5R(&!<)RX*"B`@K
XM("`@7PA27PAE7PAG7PAE7PAR7PAR7PAO7PAR"B`@("`@:7,@8V%L;&5D('=HJ
XM96YE=F5R(&%N(&5R<F]R(&ES(&1E=&5C=&5D(&EN(%\(<E\(95\(9U\(8U\(7
XM;U\(;5\(<"P@7PAR7PAE7PAG7PAE7PAX7PAE7PAC+`H@("`@(&]R(%\(<E\(Q
XM95\(9U\(<U\(=5\(8BX*("`@("!4:&4@9&5F875L="!?"')?"&5?"&=?"&5?N
XM"')?"')?"&]?"'(@=W)I=&5S('1H92!S=')I;F<@7PAM7PAS7PAG+`H@("`@J
XM('=I=&@@82!S=6ET86)L92!I;F1I8V%T;W(@;V8@;W)I9VEN+`H@("`@(&]N#
XM('1H92!S=&%N9&%R9`H@("`@(&5R<F]R(&]U='!U=`H@("`@(&%N9"!I;G9OP
XM:V5S(%\(95\(>%\(:5\(="@R*2X*("`@("!?"%)?"&5?"&=?"&5?"')?"')?$
XM"&]?"'(*("`@("!C86X@8F4@<F5P;&%C960@8GD@=&AE('5S97(@:68@;W1H(
XM97(@86-T:6]N<R!A<F4@9&5S:7)A8FQE+@H*4@A210A%1PA'50A53`A,00A!]
XM4@A2($4(15@(6%`(4%((4D4(15,(4U,(4TD(24\(3TX(3B!3"%-9"%E."$Y4\
XM"%1!"$%8"%@*("`@("!!(')E9W5L87(@97AP<F5S<VEO;B!I<R!Z97)O(&]RH
XM(&UO<F4@7PAB7PAR7PAA7PAN7PAC7PAH7PAE7PAS+"!S97!A<F%T960@8GD@1
XM8'PG+@H@("`@($ET(&UA=&-H97,@86YY=&AI;F<@=&AA="!M871C:&5S(&]NR
XM92!O9B!T:&4@8G)A;F-H97,N"@H@("`@($$@8G)A;F-H(&ES('IE<F\@;W(@/
XM;6]R92!?"'!?"&E?"&5?"&-?"&5?"',L(&-O;F-A=&5N871E9"X*("`@("!),
XM="!M871C:&5S(&$@;6%T8V@@9F]R('1H92!F:7)S="P@9F]L;&]W960@8GD@Z
XM82!M871C:"!F;W(@=&AE('-E8V]N9"P@971C+@H*("`@("!!('!I96-E(&ES_
XM(&%N(%\(85\(=%\(;U\(;2!P;W-S:6)L>2!F;VQL;W=E9"!B>2!@*B<L(&`K0
XM)RP@;W(@8#\G+@H@("`@($%N(&%T;VT@9F]L;&]W960@8GD@8"HG(&UA=&-H'
XM97,@82!S97%U96YC92!O9B`P(&]R(&UO<F4@;6%T8VAE<R!O9B!T:&4@871OJ
XM;2X*("`@("!!;B!A=&]M(&9O;&QO=V5D(&)Y(&`K)R!M871C:&5S(&$@<V5Q]
XM=65N8V4@;V8@,2!O<B!M;W)E(&UA=&-H97,@;V8@=&AE(&%T;VTN"B`@("`@N
XM06X@871O;2!F;VQL;W=E9"!B>2!@/R<@;6%T8VAE<R!A(&UA=&-H(&]F('1H!
XM92!A=&]M+"!O<B!T:&4@;G5L;"!S=')I;F<N"@H@("`@($%N(&%T;VT@:7,@4
XM82!R96=U;&%R(&5X<')E<W-I;VX@:6X@<&%R96YT:&5S97,@*&UA=&-H:6YGO
XM(&$@;6%T8V@@9F]R('1H90H@("`@(')E9W5L87(@97AP<F5S<VEO;BDL(&$@X
XM7PAR7PAA7PAN7PAG7PAE("AS964@8F5L;W<I+"!@+B<*("`@("`H;6%T8VAI`
XM;F<@86YY('-I;F=L92!C:&%R86-T97(I+"!@7B<@*&UA=&-H:6YG('1H92!N(
XM=6QL('-T<FEN9R!A="!T:&4*("`@("!B96=I;FYI;F<@;V8@=&AE(&EN<'5T;
XM('-T<FEN9RDL(&`D)R`H;6%T8VAI;F<@=&AE(&YU;&P@<W1R:6YG(&%T('1H.
XM90H*"@I&;W)M871T960@.#@O,3(O,S`@("`@("`@("`@("!L;V-A;"`@("`@2
XM("`@("`@("`@("`@("`@("`@("`@("`@,@H,"@H*"E)%1T584"@S*2`@("`@?
XM("`@("`@("`@("!,:6)R87)Y($9U;F-T:6]N<R`@("`@("`@("`@("`@(%)%%
XM1T584"@S*0H*"@H@("`@(&5N9"!O9B!T:&4@:6YP=70@<W1R:6YG*2P@82!@J
XM7"<@9F]L;&]W960@8GD@82!S:6YG;&4@8VAA<F%C=&5R("AM871C:&EN9PH@G
XM("`@('1H870@8VAA<F%C=&5R*2P@;W(@82!S:6YG;&4@8VAA<F%C=&5R('=I$
XM=&@@;F\@;W1H97(@<VEG;FEF:6-A;F-E"B`@("`@*&UA=&-H:6YG('1H870@L
XM8VAA<F%C=&5R*2X*"B`@("`@02!?"')?"&%?"&Y?"&=?"&4@:7,@82!S97%U$
XM96YC92!O9B!C:&%R86-T97)S(&5N8VQO<V5D(&EN(&!;72<N"B`@("`@270@(
XM;F]R;6%L;'D@;6%T8VAE<R!A;GD@<VEN9VQE(&-H87)A8W1E<B!F<F]M('1H:
XM92!S97%U96YC92X*("`@("!)9B!T:&4@<V5Q=65N8V4@8F5G:6YS('=I=&@@3
XM8%XG+`H@("`@(&ET(&UA=&-H97,@86YY('-I;F=L92!C:&%R86-T97(@7PANI
XM7PAO7PAT(&9R;VT@=&AE(')E<W0@;V8@=&AE('-E<75E;F-E+@H@("`@($EF:
XM('1W;R!C:&%R86-T97)S(&EN('1H92!S97%U96YC92!A<F4@<V5P87)A=&5D\
XM(&)Y(&`M)RP@=&AI<R!I<R!S:&]R=&AA;F0*("`@("!F;W(@=&AE(&9U;&P@_
XM;&ES="!O9B!!4T-)22!C:&%R86-T97)S(&)E='=E96X@=&AE;0H@("`@("AE)
XM+F<N(&!;,"TY72<@;6%T8VAE<R!A;GD@9&5C:6UA;"!D:6=I="DN"B`@("`@&
XM5&\@:6YC;'5D92!A(&QI=&5R86P@8%TG(&EN('1H92!S97%U96YC92P@;6%KO
XM92!I="!T:&4@9FER<W0@8VAA<F%C=&5R"B`@("`@*&9O;&QO=VEN9R!A('!O[
XM<W-I8FQE(&!>)RDN"B`@("`@5&\@:6YC;'5D92!A(&QI=&5R86P@8"TG+"!MJ
XM86ME(&ET('1H92!F:7)S="!O<B!L87-T(&-H87)A8W1E<BX*"D$(04T(34((Q
XM0DD(24<(1U4(54D(250(5%D(60H@("`@($EF(&$@<F5G=6QA<B!E>'!R97-S^
XM:6]N(&-O=6QD(&UA=&-H('1W;R!D:69F97)E;G0@<&%R=',@;V8@=&AE(&EN2
XM<'5T('-T<FEN9RP*("`@("!I="!W:6QL(&UA=&-H('1H92!O;F4@=VAI8V@@>
XM8F5G:6YS(&5A<FQI97-T+@H@("`@($EF(&)O=&@@8F5G:6X@:6X@=&AE('-AV
XM;64@<&QA8V4@("`@8G5T(&UA=&-H(&1I9F9E<F5N="!L96YG=&AS+"!O<B!M5
XM871C:`H@("`@('1H92!S86UE(&QE;F=T:"!I;B!D:69F97)E;G0@=V%Y<RP@Q
XM;&EF92!G971S(&UE<W-I97(L(&%S(&9O;&QO=W,N"@H@("`@($EN(&=E;F5R;
XM86PL('1H92!P;W-S:6)I;&ET:65S(&EN(&$@;&ES="!O9B!B<F%N8VAE<R!AM
XM<F4@8V]N<VED97)E9"!I;@H@("`@(&QE9G0M=&\M<FEG:'0@;W)D97(L('1HB
XM92!P;W-S:6)I;&ET:65S(&9O<B!@*B<L(&`K)RP@86YD(&`_)R!A<F4*("`@E
XM("!C;VYS:61E<F5D(&QO;F=E<W0M9FER<W0L(&YE<W1E9"!C;VYS=')U8W1S8
XM(&%R92!C;VYS:61E<F5D(&9R;VT@=&AE"B`@("`@;W5T97)M;W-T(&EN+"!A-
XM;F0@8V]N8V%T96YA=&5D(&-O;G-T<G5C=',@87)E(&-O;G-I9&5R960@;&5F"
XM=&UO<W0M9FER<W0N"B`@("`@5&AE(&UA=&-H('1H870@=VEL;"!B92!C:&]S/
XM96X@:7,@=&AE(&]N92!T:&%T('5S97,@=&AE(&5A<FQI97-T"B`@("`@<&]S9
XM<VEB:6QI='D@:6X@=&AE(&9I<G-T(&-H;VEC92!T:&%T(&AA<R!T;R!B92!MX
XM861E+@H@("`@($EF('1H97)E(&ES(&UO<F4@=&AA;B!O;F4@8VAO:6-E+"!TP
XM:&4@;F5X="!W:6QL(&)E(&UA9&4@:6X@=&AE('-A;64@;6%N;F5R"B`@("`@+
XM*&5A<FQI97-T('!O<W-I8FEL:71Y*2!S=6)J96-T('1O('1H92!D96-I<VEOY
XM;B!O;B!T:&4@9FER<W0@8VAO:6-E+@H@("`@($%N9"!S;R!F;W)T:"X*"B`@1
XM("`@1F]R(&5X86UP;&4L(&`H86)\82EB*F,G(&-O=6QD(&UA=&-H(&!A8F,GW
XM(&EN(&]N92!O9B!T=V\@=V%Y<RX*("`@("!4:&4@9FER<W0@8VAO:6-E(&EST
XM(&)E='=E96X@8&%B)R!A;F0@8&$G.R!S:6YC92!@86(G(&ES(&5A<FQI97(L2
XM(&%N9"!D;V5S"B`@("`@;&5A9"!T;R!A('-U8V-E<W-F=6P@;W9E<F%L;"!MD
XM871C:"P@:70@:7,@8VAO<V5N+@H@("`@(%-I;F-E('1H92!@8B<@:7,@86QRT
XM96%D>2!S<&]K96X@9F]R+`H@("`@('1H92!@8BHG(&UU<W0@;6%T8V@@:71S*
XM(&QA<W0@<&]S<VEB:6QI='DM+71H92!E;7!T>2!S=')I;F<M+7-I;F-E"B`@&
XM("`@:70@;75S="!R97-P96-T('1H92!E87)L:65R(&-H;VEC92X*"B`@("`@.
XM26X@=&AE('!A<G1I8W5L87(@8V%S92!W:&5R92!N;R!@?"=S(&%R92!P<F5SK
XM96YT(&%N9"!T:&5R92!I<R!O;FQY(&]N90H@("`@(&`J)RP@8"LG+"!O<B!@8
XM/R<L('1H92!N970@969F96-T(&ES('1H870@=&AE(&QO;F=E<W0@<&]S<VEBA
XM;&4*("`@("!M871C:"!W:6QL(&)E(&-H;W-E;BX*("`@("!3;R!@86(J)RP@A
XM<')E<V5N=&5D('=I=&@@8'AA8F)B8GDG+"!W:6QL(&UA=&-H(&!A8F)B8B<N6
XM"B`@("`@3F]T92!T:&%T(&EF(&!A8BHG(&ES('1R:65D(&%G86EN<W0@8'AAH
XM8GEA8F)B>B<L(&ET"B`@("`@=VEL;"!M871C:"!@86(G(&IU<W0@869T97(@=
XM8'@G+"!D=64@=&\@=&AE(&)E9VEN<RUE87)L:65S="!R=6QE+@H@("`@("A)L
XM;B!E9F9E8W0L('1H92!D96-I<VEO;B!O;B!W:&5R92!T;R!S=&%R="!T:&4@`
XM;6%T8V@@:7,@=&AE(&9I<G-T(&-H;VEC90H@("`@('1O(&)E(&UA9&4L(&AE!
XM;F-E('-U8G-E<75E;G0@8VAO:6-E<R!M=7-T(')E<W!E8W0@:70@979E;B!IV
XM9B!T:&ES(&QE861S('1H96T*("`@("!T;R!L97-S+7!R969E<G)E9"!A;'1E+
XM<FYA=&EV97,N*0H*4PA310A%10A%($$(04P(3%,(4T\(3PH@("`@(&5G<F5P$
XM*#$I+"!E>'!R*#$I"@H*"@H*1F]R;6%T=&5D(#@X+S$R+S,P("`@("`@("`@%
XM("`@;&]C86P@("`@("`@("`@("`@("`@("`@("`@("`@("`@(#,*#`H*"@I2.
XM14=%6%`H,RD@("`@("`@("`@("`@("`@3&EB<F%R>2!&=6YC=&EO;G,@("`@K
XM("`@("`@("`@("!214=%6%`H,RD*"@H*1`A$20A)00A!1PA'3@A.3PA/4PA39
XM5`A420A)0PA#4PA3"B`@("`@7PA27PAE7PAG7PAC7PAO7PAM7PAP(')E='5R@
XM;G,@3E5,3"!F;W(@82!F86EL=7)E"B`@("`@*%\(<E\(95\(9U\(95\(<E\(]
XM<E\(;U\(<B!P97)M:71T:6YG*2P*("`@("!W:&5R92!F86EL=7)E<R!A<F4@1
XM<WEN=&%X(&5R<F]R<RP@97AC965D:6YG(&EM<&QE;65N=&%T:6]N(&QI;6ETA
XM<RP*("`@("!O<B!A<'!L>6EN9R!@*R<@;W(@8"HG('1O(&$@<&]S<VEB;'DM8
XM;G5L;"!O<&5R86YD+@H*2`A(20A)4PA35`A43PA/4@A260A9"B`@("`@0F]TQ
XM:"!C;V1E(&%N9"!M86YU86P@<&%G92!W97)E"B`@("`@=W)I='1E;B!A="!5%
XM(&]F(%0N"B`@("`@5&AE>2!A<F4@:6YT96YD960@=&\@8F4@8V]M<&%T:6)LC
XM92!W:71H('1H92!"96QL(%8X(%\(<E\(95\(9U\(95\(>%\(<"@S*2P*("`@>
XM("!B=70@87)E(&YO="!D97)I=F5D(&9R;VT@0F5L;"!C;V1E+@H*0@A"50A5%
XM1PA'4PA3"B`@("`@16UP='D@8G)A;F-H97,@86YD(&5M<'1Y(')E9W5L87(@W
XM97AP<F5S<VEO;G,@87)E(&YO="!P;W)T86)L92!T;R!6."X*"B`@("`@5&AEY
XM(')E<W1R:6-T:6]N(&%G86EN<W0*("`@("!A<'!L>6EN9R!@*B<@;W(@8"LG/
XM('1O(&$@<&]S<VEB;'DM;G5L;"!O<&5R86YD(&ES(&%N(&%R=&EF86-T(&]F8
XM('1H90H@("`@('-I;7!L:7-T:6,@:6UP;&5M96YT871I;VXN"@H@("`@($1OG
XM97,@;F]T('-U<'!O<G0@7PAE7PAG7PAR7PAE7PAP)W,@;F5W;&EN92US97!A^
XM<F%T960@8G)A;F-H97,["B`@("`@;F5I=&AE<B!D;V5S('1H92!6."!?"')?\
XM"&5?"&=?"&5?"'A?"'`H,RDL('1H;W5G:"X*"B`@("`@1'5E('1O(&5M<&AA*
XM<VES(&]N"B`@("`@8V]M<&%C=&YE<W,@86YD('-I;7!L:6-I='DL"B`@("`@F
XM:70G<R!N;W0@<W1R:6MI;F=L>2!F87-T+@H@("`@($ET(&1O97,@9VEV92!SD
XM<&5C:6%L(&%T=&5N=&EO;B!T;R!H86YD;&EN9R!S:6UP;&4@8V%S97,@<75I4
XM8VML>2X*"@H*"@H*"@H*"@H*"@H*"@H*"@H*"@H*"@H*"@I&;W)M871T960@3
XM.#@O,3(O,S`@("`@("`@("`@("!L;V-A;"`@("`@("`@("`@("`@("`@("`@?
X+("`@("`@("`@-`H@^
X``
Xend
Xsize 8651
SHAR_EOF
echo "extracting regexp.h"
sed 's/^X//' << \SHAR_EOF > regexp.h
X/*
X * NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
X *
X * This is NOT the original regular expression code as written by
X * Henry Spencer. This code has been modified specifically for use
X * with the STEVIE editor, and should not be used apart from compiling
X * STEVIE. If you want a good regular expression library, get the
X * original code. The copyright notice that follows is from the
X * original.
X *
X * NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
X *
X * Definitions etc. for regexp(3) routines.
X *
X * Caveat: this is V8 regexp(3) [actually, a reimplementation thereof],
X * not the System V one.
X */
X#define NSUBEXP 10
Xtypedef struct regexp {
X char *startp[NSUBEXP];
X char *endp[NSUBEXP];
X char regstart; /* Internal use only. */
X char reganch; /* Internal use only. */
X char *regmust; /* Internal use only. */
X int regmlen; /* Internal use only. */
X char program[1]; /* Unwarranted chumminess with compiler. */
X} regexp;
X
Xextern regexp *regcomp();
Xextern int regexec();
Xextern void regsub();
Xextern void regerror();
X
X#ifndef ORIGINAL
Xextern int reg_ic; /* set non-zero to ignore case in searches */
X#endif
SHAR_EOF
echo "extracting regmagic.h"
sed 's/^X//' << \SHAR_EOF > regmagic.h
X/*
X * NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
X *
X * This is NOT the original regular expression code as written by
X * Henry Spencer. This code has been modified specifically for use
X * with the STEVIE editor, and should not be used apart from compiling
X * STEVIE. If you want a good regular expression library, get the
X * original code. The copyright notice that follows is from the
X * original.
X *
X * NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
X *
X * The first byte of the regexp internal "program" is actually this magic
X * number; the start node begins in the second byte.
X */
X#define MAGIC 0234
SHAR_EOF
echo "extracting regsub.c"
sed 's/^X//' << \SHAR_EOF > regsub.c
X/*
X * NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
X *
X * This is NOT the original regular expression code as written by
X * Henry Spencer. This code has been modified specifically for use
X * with the STEVIE editor, and should not be used apart from compiling
X * STEVIE. If you want a good regular expression library, get the
X * original code. The copyright notice that follows is from the
X * original.
X *
X * NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
X *
X * regsub
X *
X * Copyright (c) 1986 by University of Toronto.
X * Written by Henry Spencer. Not derived from licensed software.
X *
X * Permission is granted to anyone to use this software for any
X * purpose on any computer system, and to redistribute it freely,
X * subject to the following restrictions:
X *
X * 1. The author is not responsible for the consequences of use of
X * this software, no matter how awful, even if they arise
X * from defects in it.
X *
X * 2. The origin of this software must not be misrepresented, either
X * by explicit claim or by omission.
X *
X * 3. Altered versions must be plainly marked as such, and must not
X * be misrepresented as being the original software.
X *
X * $Log: regsub.c,v $
X * Revision 1.2 88/04/28 08:11:25 tony
X * First modification of the regexp library. Added an external variable
X * 'reg_ic' which can be set to indicate that case should be ignored.
X * Added a new parameter to regexec() to indicate that the given string
X * comes from the beginning of a line and is thus eligible to match
X * 'beginning-of-line'.
X *
X */
X
X#include "env.h"
X
X#ifdef MEGAMAX
Xoverlay "regexp"
X#endif
X
X#include <stdio.h>
X#include "regexp.h"
X#include "regmagic.h"
X
X#ifndef CHARBITS
X#define UCHARAT(p) ((int)*(unsigned char *)(p))
X#else
X#define UCHARAT(p) ((int)*(p)&CHARBITS)
X#endif
X
X/*
X - regsub - perform substitutions after a regexp match
X */
Xvoid
Xregsub(prog, source, dest)
X regexp *prog;
X char *source;
X char *dest;
X{
X register char *src;
X register char *dst;
X register char c;
X register int no;
X register int len;
X extern char *strncpy();
X
X if (prog == NULL || source == NULL || dest == NULL) {
X regerror("NULL parm to regsub");
X return;
X }
X if (UCHARAT(prog->program) != MAGIC) {
X regerror("damaged regexp fed to regsub");
X return;
X }
X src = source;
X dst = dest;
X while ((c = *src++) != '\0') {
X if (c == '&')
X no = 0;
X else if (c == '\\' && '0' <= *src && *src <= '9')
X no = *src++ - '0';
X else
X no = -1;
X if (no < 0) { /* Ordinary character. */
X if (c == '\\' && (*src == '\\' || *src == '&'))
X c = *src++;
X *dst++ = c;
X } else if (prog->startp[no] != NULL && prog->endp[no] != NULL) {
X len = prog->endp[no] - prog->startp[no];
X (void) strncpy(dst, prog->startp[no], len);
X dst += len;
X if (len != 0 && *(dst - 1) == '\0') { /* strncpy hit NUL. */
X regerror("damaged match string");
X return;
X }
X }
X }
X *dst = '\0';
X}
SHAR_EOF
echo "extracting s_io.c"
sed 's/^X//' << \SHAR_EOF > s_io.c
X/*
X * s_io() - routines that do screen I/O or effect what we think is
X * on the screen.
X *
X * By G. R. (Fred) Walter watmath!watcgl!grwalter
X */
X
X#include "stevie.h"
X
X/*
X * screen_ins(row, nlines, total_rows) - insert 'nlines' lines at 'row'
X *
X * NOTE: this routine assumes it is called with valid arguments.
X */
X
Xstatic void
Xscreen_ins(row, nlines, total_rows)
X int row;
X int nlines;
X int total_rows;
X{
X if (nlines < 1 || (row + nlines) > total_rows)
X return;
X
X#ifndef T_IL_B
X {
X int i;
X
X for (i = 0; i < nlines; i++) {
X windgoto(row, 0);
X outstr(T_IL);
X }
X }
X#else
X windgoto(row, 0);
X outstr(T_IL);
X if (nlines >= 10)
X outchar((char) (nlines / 10 + '0'));
X outchar((char) (nlines % 10 + '0'));
X outstr(T_IL_B);
X#endif
X
X /* delete any garbage that may have been shifted to the status line */
X windgoto(total_rows - 1, 0);
X outstr(T_EL);
X}
X
X/*
X * screen_del(row, nlines, total_rows) - delete 'nlines' lines at 'row'
X *
X * NOTE: this routine assumes it is called with valid arguments.
X */
X
Xstatic void
Xscreen_del(row, nlines, total_rows)
X int row;
X int nlines;
X int total_rows;
X{
X if (nlines < 1 || (row + nlines) > total_rows)
X return;
X
X /* delete any garbage that may have been on the status line */
X windgoto(total_rows - 1, 0);
X outstr(T_EL);
X
X#ifndef T_DL_B
X {
X int i;
X
X for (i = 0; i < nlines; i++) {
X windgoto(row, 0);
X outstr(T_DL); /* delete a line */
X }
X }
X#else
X windgoto(row, 0);
X outstr(T_DL);
X if (nlines >= 10)
X outchar((char) (nlines / 10 + '0'));
X outchar((char) (nlines % 10 + '0'));
X outstr(T_DL_B);
X#endif
X}
X
X/*
X * screen_refresh()
X *
X * Based on the current value of Topchar, refresh the contents of the screen
X * and update Botchar.
X */
X
Xstatic void
Xscreen_refresh(type)
X int type;
X{
X char *ptr;
X int total_rows;
X int row;
X int col;
X LINE *memp;
X LPtr start;
X bool_t off_top;
X bool_t done; /* if TRUE, we hit the end of the file */
X bool_t didline; /* if TRUE, we finished the last line */
X int lno; /* number of the line we're doing */
X int coff;
X int idx;
X int i;
X int j;
X
X if (NumLineSizes <= 0)
X type = NOT_VALID;
X
X if (!RedrawingDisabled)
X outstr(T_CI);
X
X off_top = FALSE;
X idx = 0;
X row = 0;
X total_rows = Rows - 1;
X memp = Topchar->linep;
X
X if ((type == VALID) || (type == VALID_TO_CURSCHAR)) {
X j = -1;
X for (i = 0; i < NumLineSizes; i++) {
X if (LinePointers[i] == memp) {
X j = i;
X break;
X }
X row += LineSizes[i];
X }
X if (j == -1) {
X /* Are we off the top of the screen by one line ? */
X if (memp->next == LinePointers[0]) {
X i = plines(Topchar->linep->s);
X if (i < (total_rows)) {
X off_top = TRUE;
X for (idx = NumLineSizes; idx > 0; idx--) {
X LinePointers[idx] = LinePointers[idx - 1];
X LineSizes[idx] = LineSizes[idx - 1];
X }
X LineSizes[idx] = (char) i;
X if (!RedrawingDisabled)
X screen_ins(0, i, Rows);
X }
X }
X row = 0;
X } else if (j == 0 && type == VALID) {
X if (!RedrawingDisabled)
X outstr(T_CV);
X return;
X } else {
X if (!RedrawingDisabled)
X screen_del(0, row, Rows);
X row = 0;
X for (;;) {
X LineSizes[idx] = LineSizes[j];
X LinePointers[idx] = LinePointers[j];
X
X if (type == VALID_TO_CURSCHAR) {
X if (LinePointers[idx] == Curschar->linep) {
X memp = LinePointers[idx];
X break;
X }
X }
X j++;
X if (j >= NumLineSizes) {
X memp = LinePointers[idx];
X if (memp->next != Fileend->linep) {
X row += LineSizes[idx];
X idx++;
X memp = memp->next;
X }
X break;
X }
X row += LineSizes[idx];
X idx++;
X }
X }
X }
X coff = 0;
X if (P(P_NU)) {
X coff = 8;
X start.linep = memp;
X lno = cntllines(Filemem, &start);
X }
X didline = TRUE;
X done = FALSE;
X
X for (;;) {
X ptr = format_line(memp->s, &col);
X i = 1 + ((col - 1) / Columns);
X if ((row + i) <= total_rows) {
X LinePointers[idx] = memp;
X LineSizes[idx++] = (char) i;
X if (!RedrawingDisabled) {
X windgoto(row, 0);
X
X if (P(P_NU))
X outstr(mkline(lno++));
X outstr(ptr);
X
X j = col + coff;
X col = j % Columns;
X if ((col != 0) || (j == 0)) {
X#ifdef T_END_L
X windgoto(row + i - 1, col);
X outstr(T_END_L);
X#else
X for (; col < Columns; col++)
X outchar(' ');
X#endif
X }
X }
X row += i;
X if (memp->next != Fileend->linep) {
X memp = memp->next;
X } else {
X done = TRUE;
X break;
X }
X if (off_top)
X break;
X } else {
X didline = FALSE;
X break;
X }
X }
X
X /* Do we have to do off the top of the screen processing ? */
X if (off_top && !done) {
X row = 0;
X for (idx = 0; idx <= NumLineSizes && row < total_rows; idx++) {
X row += LineSizes[idx];
X }
X
X idx--;
X
X if (row < total_rows) {
X done = TRUE;
X idx++;
X } else if (row > total_rows) {
X row -= LineSizes[idx];
X didline = FALSE;
X memp = LinePointers[idx];
X } else {
X didline = TRUE;
X memp = LinePointers[idx]->next;
X idx++;
X }
X }
X NumLineSizes = idx;
X
X /*
X * If we didn't hit the end of the file, and we didn't finish the last
X * line we were working on, then the line didn't fit.
X */
X if (!done && !didline) {
X if (!RedrawingDisabled) {
X /* Clear the rest of the screen. */
X#ifdef T_END_D
X windgoto(row, 0);
X outstr(T_END_D);
X#else
X screen_del(row, total_rows - row, Rows);
X windgoto(row, 0);
X#endif
X /* put '@'s on rows that are part of a line that's too long */
X for (; row < total_rows; row++)
X outstr("@\n\r");
X }
X Botchar->linep = memp;
X } else {
X if (!RedrawingDisabled && !off_top) {
X /* Clear the rest of the screen. */
X#ifdef T_END_D
X windgoto(row, 0);
X outstr(T_END_D);
X#else
X screen_del(row, total_rows - row, Rows);
X windgoto(row, 0);
X#endif
X /* put '~'s on rows that aren't part of the file. */
X for (; row < total_rows; row++)
X outstr("~\n\r");
X }
X if (done) /* we hit the end of the file */
X *Botchar = *Fileend;
X else
X Botchar->linep = memp; /* FIX - prev? */
X }
X
X if (!RedrawingDisabled)
X outstr(T_CV);
X}
X
X/*
X * s_refresh()
X *
X * Based on the current value of Curschar, (if necessary) update Topchar and
X * Botchar and refresh the screen contensts.
X */
X
Xvoid
Xs_refresh(type)
X int type;
X{
X LPtr *p;
X LPtr *pp;
X int i;
X int nlines;
X int refreshed;
X
X refreshed = FALSE;
X
X if (bufempty()) { /* special case - file is empty */
X *Topchar = *Filemem;
X *Curschar = *Filemem;
X screen_refresh(NOT_VALID);
X return;
X }
X if (NumLineSizes < 0) {
X type = NOT_VALID;
X }
X if (type != VALID) {
X screen_refresh(type);
X refreshed = TRUE;
X type = VALID;
X }
X if (LINEOF(Curschar) < LINEOF(Topchar)) {
X nlines = cntllines(Curschar, Topchar);
X /*
X * if the cursor is above the top of the screen, put it at the top of
X * the screen..
X */
X *Topchar = *Curschar;
X Topchar->index = 0;
X /*
X * ... and, if we weren't very close to begin with, we scroll so that
X * the line is close to the middle.
X */
X if (nlines > Rows / 3) {
X p = Topchar;
X for (i = 0; i < Rows / 3; i += plines(p->linep->s)) {
X pp = prevline(p);
X if (pp == NULL)
X break;
X p = pp;
X }
X *Topchar = *p;
X }
X screen_refresh(VALID);
X } else if (LINEOF(Curschar) >= LINEOF(Botchar)) {
X nlines = cntllines(Botchar, Curschar);
X /*
X * If the cursor is off the bottom of the screen, put it at the top
X * of the screen.. ... and back up
X */
X if (nlines > Rows / 3) {
X p = Curschar;
X for (i = 0; i < (2 * Rows) / 3; i += plines(p->linep->s)) {
X pp = prevline(p);
X if (pp == NULL)
X break;
X p = pp;
X }
X *Topchar = *p;
X } else {
X scrollup(nlines);
X }
X screen_refresh(VALID);
X } else if (refreshed == FALSE) {
X screen_refresh(type);
X }
X /* Check if we are below Botchar (this can occur). */
X if (LINEOF(Curschar) == LINEOF(Botchar)) {
X pp = nextline(Topchar);
X if (pp != NULL) {
X Topchar->linep = pp->linep;
X screen_refresh(VALID);
X }
X } else if (LINEOF(Curschar) > LINEOF(Botchar)) {
X nlines = cntllines(Botchar, Curschar);
X /*
X * If the cursor is off the bottom of the screen, put it at the top
X * of the screen.. ... and back up
X */
X if (nlines > Rows / 3) {
X p = Curschar;
X for (i = 0; i < (2 * Rows) / 3; i += plines(p->linep->s)) {
X pp = prevline(p);
X if (pp == NULL)
X break;
X p = pp;
X }
X *Topchar = *p;
X } else {
X scrollup(nlines);
X }
X screen_refresh(VALID);
X }
X}
X
X/*
X * s_clear() - clear the screen and mark the stored information as invalid.
X */
Xvoid
Xs_clear()
X{
X outstr(T_ED); /* clear the display */
X S_NOT_VALID;
X}
X
X/*
X * Update_Botchar()
X *
X * Based on the current value of Topchar update Botchar.
X */
X
Xvoid
XUpdate_Botchar()
X{
X int row;
X LINE *memp;
X int total_rows;
X int i;
X
X row = 0;
X total_rows = Rows - 1;
X memp = Topchar->linep;
X
X for (;;) {
X i = plines(memp->s);
X if ((row + i) <= total_rows) {
X row += i;
X memp = memp->next;
X if (memp == Fileend->linep)
X break;
X } else {
X break;
X }
X }
X Botchar->linep = memp;
X
X MustUpdateBotchar = FALSE;
X}
X
X#ifdef DONTINCLUDEANYMORE
X/*
X * NotValidFromCurschar()
X *
X * Mark the lines in NumLinePointers and NumLineSizes from Curschar on as
X * not valid.
X */
X
Xvoid
XNotValidFromCurschar()
X{
X register int idx;
X register unsigned long num;
X
X S_VALID_TO_CURSCHAR;
X
X num = LINEOF(Curschar);
X for (idx = 0; idx < NumLineSizes; idx++) {
X if (LinePointers[idx]->num >= num)
X break;
X }
X NumLineSizes = idx;
X}
X#endif
SHAR_EOF
echo "extracting screen.c"
sed 's/^X//' << \SHAR_EOF > screen.c
X/*
X * STEVIE - Simply Try this Editor for VI Enthusiasts
X *
X * Code Contributions By : Tim Thompson twitch!tjt
X * Tony Andrews onecom!wldrdg!tony
X * G. R. (Fred) Walter watmath!watcgl!grwalter
X */
X
X#include "stevie.h"
X
X/*
X * The following variable is set (in cursupdate) to the number of physical
X * lines taken by the line the cursor is on. We use this to avoid extra calls
X * to plines(). The optimized routine updateline() makes sure that the size of
X * the cursor line hasn't changed. If so, lines below the cursor will move up
X * or down and we need to call the routine s_refresh() to examine the
X * entire screen.
X */
Xstatic int Cline_size; /* size (in rows) of the cursor line */
Xstatic int Cline_row; /* starting row of the cursor line */
X
X/*
X * updateline() - like s_refresh() but only for cursor line
X *
X * This determines whether or not we need to call s_refresh() to examine
X * the entire screen for changes. This occurs if the size of the cursor line
X * (in rows) has changed.
X */
Xstatic void
Xupdateline()
X{
X char *ptr;
X int col;
X int size;
X int j;
X
X if (RedrawingDisabled) /* Is this the correct action ? */
X return;
X
X ptr = format_line(Curschar->linep->s, &col);
X
X size = 1 + ((col - 1) / Columns);
X if (Cline_size == size) {
X outstr(T_CI);
X windgoto(Cline_row, 0);
X if (P(P_NU)) {
X /*
X * This should be done more efficiently.
X */
X outstr(mkline(cntllines(Filemem, Curschar)));
X }
X outstr(ptr);
X
X j = col + (P(P_NU) ? 8 : 0);
X col = j % Columns;
X if ((col != 0) || (j == 0)) {
X#ifdef T_END_L
X windgoto(Cline_row + size - 1, col);
X outstr(T_END_L);
X#else
X for (; col < Columns; col++)
X outchar(' ');
X#endif
X }
X outstr(T_CV);
X } else {
X s_refresh(VALID_TO_CURSCHAR);
X }
X}
X
Xvoid
Xcursupdate(type)
X int type;
X{
X register char c;
X register int incr;
X register int i;
X register int didincr;
X
X if (MustUpdateBotchar == TRUE)
X Update_Botchar();
X
X if (NumLineSizes < 0) {
X s_refresh(NOT_VALID);
X } else {
X if (LineNotValid == TRUE)
X updateline();
X
X if (type != UPDATE_CURSOR) {
X s_refresh(type);
X } else if (ValidToCurschar == TRUE) {
X s_refresh(VALID_TO_CURSCHAR);
X } else if (CheckTopcharAndBotchar == TRUE) {
X s_refresh(VALID);
X }
X }
X
X CheckTopcharAndBotchar = FALSE;
X MustUpdateBotchar = FALSE;
X ValidToCurschar = FALSE;
X LineNotValid = FALSE;
X
X Cursrow = Curscol = Cursvcol = i = 0;
X for (i = 0; i < NumLineSizes; i++) {
X if (LinePointers[i] == Curschar->linep)
X break;
X Cursrow += LineSizes[i];
X }
X
X if (P(P_NU))
X Curscol = 8;
X
X Cline_row = Cursrow;
X Cline_size = LineSizes[i];
X
X for (i = 0; i <= Curschar->index; i++) {
X c = Curschar->linep->s[i];
X /* A tab gets expanded, depending on the current column */
X if (c == TAB && !P(P_LS))
X incr = P(P_TS) - (Cursvcol % P(P_TS));
X else
X incr = chars[c].ch_size;
X Curscol += incr;
X Cursvcol += incr;
X if (Curscol >= Columns) {
X Curscol -= Columns;
X Cursrow++;
X didincr = TRUE;
X } else
X didincr = FALSE;
X }
X if (didincr)
X Cursrow--;
X
X if (c == TAB && State == NORMAL && !P(P_LS)) {
X Curscol--;
X Cursvcol--;
X } else {
X Curscol -= incr;
X Cursvcol -= incr;
X }
X if (Curscol < 0)
X Curscol += Columns;
X
X if (set_want_col) {
X Curswant = Cursvcol;
X set_want_col = FALSE;
X }
X}
SHAR_EOF
echo "extracting search.c"
sed 's/^X//' << \SHAR_EOF > search.c
X/*
X * STEVIE - Simply Try this Editor for VI Enthusiasts
X *
X * Code Contributions By : Tim Thompson twitch!tjt
X * Tony Andrews onecom!wldrdg!tony
X * G. R. (Fred) Walter watmath!watcgl!grwalter
X */
X
X#include "stevie.h"
X/* modified Henry Spencer's regular expression routines */
X#include "regexp.h"
X
X#ifdef MEGAMAX
Xoverlay "search"
X#endif
X
X/*
X * This file contains various searching-related routines. These fall into
X * three groups: string searches (for /, ?, n, and N), character searches
X * within a single line (for f, F, t, T, etc), and "other" kinds of searches
X * like the '%' command, and 'word' searches.
X */
X
X/*
X * String searches
X *
X * The actual searches are done using Henry Spencer's regular expression
X * library.
X */
X
X#define BEGWORD "([^a-zA-Z0-9_]|^)" /* replaces "\<" in search strings */
X#define ENDWORD "([^a-zA-Z0-9_]|$)" /* likewise replaces "\>" */
X
Xbool_t begword; /* does the search include a 'begin word'
X * match */
X
X/*
X * mapstring(s) - map special backslash sequences
X */
Xstatic char *
Xmapstring(s)
X register char *s;
X{
X static char ns[MAX_COLUMNS + 1];
X register char *p;
X
X begword = FALSE;
X
X for (p = ns; *s; s++) {
X if ((*s == '(') || (*s == ')')) {
X *p++ = '\\';
X *p++ = *s;
X continue;
X }
X if (*s != '\\') { /* not an escape */
X *p++ = *s;
X continue;
X }
X switch (*++s) {
X case '/':
X *p++ = '/';
X break;
X
X case '<':
X strcpy(p, BEGWORD);
X p += strlen(BEGWORD);
X begword = TRUE;
X break;
X
X case '>':
X strcpy(p, ENDWORD);
X p += strlen(ENDWORD);
X break;
X
X default:
X *p++ = '\\';
X *p++ = *s;
X break;
X }
X }
X *p = NUL;
X
X return ns;
X}
X
Xstatic LPtr *
Xbcksearch(str)
X char *str;
X{
X static LPtr infile;
X register LPtr *p;
X regexp *prog;
X register char *s;
X register int i;
X bool_t want_start = (*str == '^'); /* looking for start of line? */
X register char *match;
X
X /* make sure str isn't empty */
X if (str == NULL || *str == NUL)
X return NULL;
X
X prog = regcomp(str);
X if (prog == NULL) {
X emsg("Invalid search string");
X return NULL;
X }
X p = Curschar;
X dec(p);
X
X if (begword) /* so we don't get stuck on one match */
X dec(p);
X
X i = (want_start) ? 0 : p->index;
X
X do {
X s = p->linep->s;
X
X if (regexec(prog, s, TRUE)) { /* match somewhere on line */
X
X if (want_start) { /* could only have been one */
X infile.linep = p->linep;
X infile.index = (int) (prog->startp[0] - s);
X free((char *) prog);
X return (&infile);
X }
X /*
X * Now, if there are multiple matches on this line, we have to
X * get the last one. Or the last one before the cursor, if we're
X * on that line.
X */
X
X match = prog->startp[0];
X
X while (regexec(prog, prog->endp[0], FALSE)) {
X if ((i >= 0) && ((prog->startp[0] - s) > i))
X break;
X match = prog->startp[0];
X }
X
X if ((i >= 0) && ((match - s) > i)) {
X i = -1;
X continue;
X }
X infile.linep = p->linep;
X infile.index = (int) (match - s);
X free((char *) prog);
X return (&infile);
X }
X i = -1;
X
X } while ((p = prevline(p)) != NULL);
X
X /*
X * If wrapscan isn't set, bag the search now
X */
X if (!P(P_WS)) {
X free((char *) prog);
X return NULL;
X }
X /* search backward from the end of the file */
X p = prevline(Fileend);
X do {
X s = p->linep->s;
X
X if (regexec(prog, s, TRUE)) { /* match somewhere on line */
X
X if (want_start) { /* could only have been one */
X infile.linep = p->linep;
X infile.index = (int) (prog->startp[0] - s);
X free((char *) prog);
X return (&infile);
X }
X /*
X * Now, if there are multiple matches on this line, we have to
X * get the last one.
X */
X
X match = prog->startp[0];
X
X while (regexec(prog, prog->endp[0], FALSE))
X match = prog->startp[0];
X
X infile.linep = p->linep;
X infile.index = (int) (match - s);
X free((char *) prog);
X return (&infile);
X }
X if (p->linep == Curschar->linep)
X break;
X
X } while ((p = prevline(p)) != NULL);
X
X free((char *) prog);
X return NULL;
X}
X
Xstatic LPtr *
Xfwdsearch(str)
X char *str;
X{
X static LPtr infile;
X LPtr *p;
X regexp *prog;
X bool_t want_start = (*str == '^'); /* looking for start of line? */
X
X char *s;
X int i;
X
X prog = regcomp(str);
X if (prog == NULL) {
X emsg("Invalid search string");
X return NULL;
X }
X p = Curschar;
X i = Curschar->index + 1;
X do {
X s = p->linep->s + i;
X i = 0;
X
X if (regexec(prog, s, i == 0)) { /* got a match */
X /*
X * If we wanted the start of a line and we aren't really there,
X * then a match doesn't count.
X */
X if (want_start && (s != p->linep->s))
X continue;
X
X infile.linep = p->linep;
X infile.index = (int) (prog->startp[0] - p->linep->s);
X free((char *) prog);
X return (&infile);
X }
X } while ((p = nextline(p)) != NULL);
X
X /*
X * If wrapscan isn't set, then don't scan from the beginning of the file.
X * Just return failure here.
X */
X if (!P(P_WS)) {
X free((char *) prog);
X return NULL;
X }
X /* search from the beginning of the file to Curschar */
X for (p = Filemem; p != NULL; p = nextline(p)) {
X s = p->linep->s;
X
X if (regexec(prog, s, TRUE)) { /* got a match */
X infile.linep = p->linep;
X infile.index = (int) (prog->startp[0] - s);
X free((char *) prog);
X return (&infile);
X }
X if (p->linep == Curschar->linep)
X break;
X }
X
X free((char *) prog);
X return (NULL);
X}
X
Xstatic char *laststr = NULL;
Xstatic int lastsdir;
X
Xstatic LPtr *
Xssearch(dir, str)
X int dir; /* FORWARD or BACKWARD */
X char *str;
X{
X LPtr *pos;
X
X reg_ic = P(P_IC); /* tell the regexp routines how to search */
X
X if (laststr != str) {
X if (laststr != NULL)
X free(laststr);
X laststr = strsave(str);
X }
X lastsdir = dir;
X
X if (dir == BACKWARD)
X pos = bcksearch(mapstring(str));
X else
X pos = fwdsearch(mapstring(str));
X
X /*
X * This is kind of a kludge, but its needed to make 'beginning of word'
X * searches land on the right place.
X */
X if (pos != NULL && begword) {
X if (pos->index != 0)
X pos->index += 1;
X }
X return pos;
X}
X
Xbool_t
Xdosearch(dir, str)
X int dir;
X char *str;
X{
X LPtr *p;
X
X S_CHECK_TOPCHAR_AND_BOTCHAR;
X
X if ((p = ssearch(dir, str)) == NULL) {
X msg("Pattern not found");
X return (FALSE);
X } else {
X LPtr savep;
X
X /* if we're backing up, we make sure the line we're on */
X /* is on the screen. */
X setpcmark();
X *Curschar = savep = *p;
X
X return (TRUE);
X }
X}
X
Xvoid
Xsearchagain(dir)
X int dir;
X{
X if (laststr == NULL)
X beep();
X else
X dosearch(dir, laststr);
X
X lastsdir = dir;
X}
X
X#define OTHERDIR(x) (((x) == FORWARD) ? BACKWARD : FORWARD)
X
Xbool_t
Xrepsearch(flag)
X bool_t flag;
X{
X int dir = lastsdir;
X bool_t found;
X
X if (laststr == NULL) {
X beep();
X return FALSE;
X }
X found = dosearch(flag ? OTHERDIR(lastsdir) : lastsdir, laststr);
X
X /*
X * We have to save and restore 'lastsdir' because it gets munged by
X * ssearch() and winds up saving the wrong direction from here if 'flag'
X * is true.
X */
X lastsdir = dir;
X
X return (found);
X}
X
X/*
X * regerror - called by regexp routines when errors are detected.
X */
Xvoid
Xregerror(s)
X char *s;
X{
X emsg(s);
X}
X
X/*
X * dosub(lp, up, cmd)
X *
X * Perform a substitution from line 'lp' to line 'up' using the
X * command pointed to by 'cmd' which should be of the form:
X *
X * /pattern/substitution/g
X *
X * The trailing 'g' is optional and, if present, indicates that multiple
X * substitutions should be performed on each line, if applicable.
X * The usual escapes are supported as described in the regexp docs.
X */
X
Xvoid
Xdosub(lp, up, cmd)
X LPtr *lp, *up;
X char *cmd;
X{
X LINE *cp;
X char *pat, *sub;
X regexp *prog;
X int nsubs;
X bool_t do_all; /* do multiple substitutions per line */
X int n;
X
X /*
X * If no range was given, do the current line. If only one line was
X * given, just do that one.
X */
X if (lp->linep == NULL)
X *up = *lp = *Curschar;
X else {
X if (up->linep == NULL)
X *up = *lp;
X }
X
X pat = ++cmd; /* skip the initial '/' */
X
X while (*cmd) {
X if (cmd[0] == '/' && cmd[-1] != '\\') {
X *cmd++ = NUL;
X break;
X }
X cmd++;
X }
X
X if (*pat == NUL) {
X emsg("NULL pattern specified");
X return;
X }
X sub = cmd;
X
X do_all = FALSE;
X
X while (*cmd) {
X if (cmd[0] == '/' && cmd[-1] != '\\') {
X do_all = (cmd[1] == 'g');
X *cmd = NUL;
X break;
X }
X cmd++;
X }
X
X reg_ic = P(P_IC); /* set "ignore case" flag appropriately */
X
X prog = regcomp(pat);
X if (prog == NULL) {
X emsg("Invalid search string");
X return;
X }
X nsubs = 0;
X
X ResetBuffers();
X n = RowNumber(lp);
X
X cp = lp->linep;
X for (; cp != Fileend->linep && cp != NULL; cp = cp->next, n++) {
X if (regexec(prog, cp->s, TRUE)) { /* a match on this line */
X char *ns, *sns, *p;
X
X /*
X * Save the line that was last changed for the final cursor
X * position (just like the real vi).
X */
X Curschar->linep = cp;
X
X /*
X * Get some space for a temporary buffer to do the substitution
X * into.
X */
X sns = ns = alloc(2048);
X if (ns == NULL)
X break;
X
X *sns = NUL;
X
X p = cp->s;
X
X do {
X for (ns = sns; *ns; ns++);
X /*
X * copy up to the part that matched
X */
X while (p < prog->startp[0])
X *ns++ = *p++;
X
X regsub(prog, sub, ns);
X
X /*
X * continue searching after the match
X */
X p = prog->endp[0];
X
X } while (regexec(prog, p, FALSE) && do_all);
X
X for (ns = sns; *ns; ns++);
X
X /*
X * copy the rest of the line, that didn't match
X */
X while (*p)
X *ns++ = *p++;
X
X *ns = NUL;
X
X AppendPositionToUndoUndobuff(0, n);
X AppendPositionToUndobuff(0, n);
X AppendToUndoUndobuff("c$");
X AppendToUndobuff("c$");
X AppendToUndoUndobuff(sns);
X AppendToUndobuff(cp->s);
X AppendToUndoUndobuff(ESC_STR);
X AppendToUndobuff(ESC_STR);
X
X free(cp->s); /* free the original line */
X cp->s = strsave(sns); /* and save the modified str */
X cp->size = strlen(cp->s) + 1;
X free(sns); /* free the temp buffer */
X nsubs++;
X }
X if (cp == up->linep)
X break;
X }
X
X if (nsubs) {
X CHANGED;
X S_NOT_VALID;
X AppendPositionToUndoUndobuff(0, 1);
X AppendPositionToUndobuff(0, 1);
X beginline(TRUE);
X if (nsubs >= P(P_RP))
X smsg("%d substitution%c", nsubs, (nsubs > 1) ? 's' : ' ');
X } else
X msg("No match");
X
X free((char *) prog);
X}
X
X/*
X * doglob(cmd)
X *
X * Execute a global command of the form:
X *
X * g/pattern/X
X *
X * where 'x' is a command character, currently one of the following:
X *
X * d Delete all matching lines
X * p Print all matching lines
X *
X * The command character (as well as the trailing slash) is optional, and
X * is assumed to be 'p' if missing.
X */
X
Xvoid
Xdoglob(lp, up, cmd)
X LPtr *lp, *up;
X char *cmd;
X{
X LINE *cp;
X
X char *pat;
X regexp *prog;
X int ndone;
X char cmdchar = NUL; /* what to do with matching lines */
X int nu;
X int nuu = 0;
X
X /*
X * If no range was given, do every line. If only one line was given, just
X * do that one.
X */
X if (lp->linep == NULL) {
X *lp = *Filemem;
X *up = *Fileend;
X } else {
X if (up->linep == NULL)
X *up = *lp;
X }
X
X pat = ++cmd; /* skip the initial '/' */
X
X while (*cmd) {
X if (cmd[0] == '/' && cmd[-1] != '\\') {
X cmdchar = cmd[1];
X *cmd = NUL;
X break;
X }
X cmd++;
X }
X if (cmdchar == NUL)
X cmdchar = 'p';
X
X reg_ic = P(P_IC); /* set "ignore case" flag appropriately */
X
X if (cmdchar != 'd' && cmdchar != 'p') {
X emsg("Invalid command character");
X return;
X }
X prog = regcomp(pat);
X if (prog == NULL) {
X emsg("Invalid search string");
X return;
X }
X msg("");
X ndone = 0;
X
X nu = RowNumber(lp);
X if (cmdchar == 'd') {
X ResetBuffers();
X nuu = nu;
X }
X cp = lp->linep;
X for (; cp != Fileend->linep && cp != NULL; cp = cp->next, nu++) {
X if (regexec(prog, cp->s, TRUE)) { /* a match on this line */
X Curschar->linep = cp;
X Curschar->index = 0;
X
X switch (cmdchar) {
X
X case 'd': /* delete the line */
X AppendPositionToUndoUndobuff(0, nuu);
X AppendToUndoUndobuff("dd");
X if (buf1line() && (ndone == 0)) {
X AppendToUndobuff("a");
X } else if (buf1line()) {
X AppendToUndobuff("j");
X AppendToUndobuff("I");
X } else if (cp->next == Fileend->linep) {
X AppendPositionToUndobuff(0, nu);
X AppendToUndobuff("o");
X } else {
X AppendPositionToUndobuff(0, nu);
X AppendToUndobuff("O");
X }
X AppendToUndobuff(cp->s);
X AppendToUndobuff(ESC_STR);
X
X delline(1);
X break;
X
X case 'p': /* print the line */
X if (P(P_NU)) {
X outstr(mkline(nu));
X }
X outstr(T_CV);
X outstr(format_line(cp->s, (int *) NULL));
X outstr(T_CI);
X outstr("\r\n");
X break;
X }
X ndone++;
X } else if (cmdchar == 'd') {
X nuu++;
X }
X if (cp == up->linep)
X break;
X }
X
X if (ndone) {
X switch (cmdchar) {
X
X case 'd':
X S_NOT_VALID;
X AppendPositionToUndobuff(0, 1);
X if (ndone >= P(P_RP))
X smsg("%d fewer line%c", ndone,
X (ndone > 1) ? 's' : ' ');
X break;
X
X case 'p':
X wait_return();
X break;
X }
X stuffReadbuff("^");
X } else
X msg("No match");
X
X free((char *) prog);
X}
X
X/*
X * Character Searches
X */
X
Xstatic char lastc = NUL; /* last character searched for */
Xstatic int lastcdir; /* last direction of character search */
Xstatic int lastctype; /* last type of search ("find" or "to") */
X
X/*
X * searchc(c, dir, type)
X *
X * Search for character 'c', in direction 'dir'. If type is 0, move to the
X * position of the character, otherwise move to just before the char.
X */
Xbool_t
Xsearchc(c, dir, type)
X char c;
X int dir;
X int type;
X{
X LPtr save;
X
X save = *Curschar; /* save position in case we fail */
X lastc = c;
X lastcdir = dir;
X lastctype = type;
X
X /*
X * On 'to' searches, skip one to start with so we can repeat searches in
X * the same direction and have it work right.
X */
X if (type)
X (dir == FORWARD) ? oneright() : oneleft();
X
X while ((dir == FORWARD) ? oneright() : oneleft()) {
X if (gchar(Curschar) == c) {
X if (type)
X (dir == FORWARD) ? oneleft() : oneright();
X return TRUE;
X }
X }
X *Curschar = save;
X return FALSE;
X}
X
Xbool_t
Xcrepsearch(flag)
X int flag;
X{
X int dir = lastcdir;
X int rval;
X
X if (lastc == NUL)
X return FALSE;
X
X rval = searchc(lastc, flag ? OTHERDIR(lastcdir) : lastcdir, lastctype);
X
X lastcdir = dir; /* restore dir., since it may have changed */
X
X return rval;
X}
X
X/*
X * "Other" Searches
X */
X
X/*
X * showmatch - move the cursor to the matching paren or brace
X */
XLPtr *
Xshowmatch()
X{
X static LPtr pos;
X int (*move) (), inc(), dec();
X char initc = gchar(Curschar); /* initial char */
X char findc; /* terminating char */
X char c;
X int count = 0;
X
X pos = *Curschar; /* set starting point */
X
X switch (initc) {
X
X case '(':
X findc = ')';
X move = inc;
X break;
X case ')':
X findc = '(';
X move = dec;
X break;
X case '{':
X findc = '}';
X move = inc;
X break;
X case '}':
X findc = '{';
X move = dec;
X break;
X case '[':
X findc = ']';
X move = inc;
X break;
X case ']':
X findc = '[';
X move = dec;
X break;
X default:
X return (LPtr *) NULL;
X }
X
X while ((*move) (&pos) != -1) { /* until end of file */
X c = gchar(&pos);
X if (c == initc)
X count++;
X else if (c == findc) {
X if (count == 0)
X return &pos;
X count--;
X }
X }
X return (LPtr *) NULL; /* never found it */
X}
X
X/*
X * findfunc(dir) - Find the next function in direction 'dir'
X *
X * Return TRUE if a function was found.
X */
Xbool_t
Xfindfunc(dir)
X int dir;
X{
X LPtr *curr;
X
X S_CHECK_TOPCHAR_AND_BOTCHAR;
X
X curr = Curschar;
X
X do {
X curr = (dir == FORWARD) ? nextline(curr) : prevline(curr);
X
X if (curr != NULL && curr->linep->s[0] == '{') {
X setpcmark();
X *Curschar = *curr;
X return TRUE;
X }
X } while (curr != NULL);
X
X return FALSE;
X}
X
X/*
X * The following routines do the word searches performed by the 'w', 'W',
X * 'b', 'B', 'e', and 'E' commands.
X */
X
X/*
X * To perform these searches, characters are placed into one of three
X * classes, and transitions between classes determine word boundaries.
X *
X * The classes are:
X *
X * 0 - white space 1 - letters, digits, and underscore 2 - everything else
X */
X
Xstatic int stype; /* type of the word motion being performed */
X
X#define C0(c) (((c) == ' ') || ((c) == '\t') || ((c) == NUL))
X#define C1(c) (isalpha(c) || isdigit(c) || ((c) == '_'))
X
X/*
X * cls(c) - returns the class of character 'c'
X *
X * The 'type' of the current search modifies the classes of characters if a 'W',
X * 'B', or 'E' motion is being done. In this case, chars. from class 2 are
X * reported as class 1 since only white space boundaries are of interest.
X */
Xstatic int
Xcls(c)
X char c;
X{
X if (C0(c))
X return 0;
X
X if (C1(c))
X return 1;
X
X /*
X * If stype is non-zero, report these as class 1.
X */
X return (stype == 0) ? 2 : 1;
X}
X
X
X/*
X * fwd_word(pos, type) - move forward one word
X *
X * Returns the resulting position, or NULL if EOF was reached.
X */
XLPtr *
Xfwd_word(p, type)
X LPtr *p;
X int type;
X{
X static LPtr pos;
X int sclass = cls(gchar(p)); /* starting class */
X
X S_CHECK_TOPCHAR_AND_BOTCHAR;
X
X pos = *p;
X
X stype = type;
X
X /*
X * We always move at least one character.
X */
X if (inc(&pos) == -1)
X return NULL;
X
X if (sclass != 0) {
X while (cls(gchar(&pos)) == sclass) {
X if (inc(&pos) == -1)
X return NULL;
X }
X /*
X * If we went from 1 -> 2 or 2 -> 1, return here.
X */
X if (cls(gchar(&pos)) != 0)
X return &pos;
X }
X /* We're in white space; go to next non-white */
X
X while (cls(gchar(&pos)) == 0) {
X /*
X * We'll stop if we land on a blank line
X */
X if (pos.index == 0 && pos.linep->s[0] == NUL)
X break;
X
X if (inc(&pos) == -1)
X return NULL;
X }
X
X return &pos;
X}
X
X/*
X * bck_word(pos, type) - move backward one word
X *
X * Returns the resulting position, or NULL if top-of-file was reached.
X */
XLPtr *
Xbck_word(p, type)
X LPtr *p;
X int type;
X{
X static LPtr pos;
X int sclass = cls(gchar(p)); /* starting class */
X
X S_CHECK_TOPCHAR_AND_BOTCHAR;
X
X pos = *p;
X
X stype = type;
X
X if (dec(&pos) == -1)
X return NULL;
X
X /*
X * If we're in the middle of a word, we just have to back up to the start
X * of it.
X */
X if (cls(gchar(&pos)) == sclass && sclass != 0) {
X /*
X * Move backward to start of the current word
X */
X while (cls(gchar(&pos)) == sclass) {
X if (dec(&pos) == -1)
X return NULL;
X }
X inc(&pos); /* overshot - forward one */
X return &pos;
X }
X /*
X * We were at the start of a word. Go back to the start of the prior
X * word.
X */
X
X while (cls(gchar(&pos)) == 0) { /* skip any white space */
X /*
X * We'll stop if we land on a blank line
X */
X if (pos.index == 0 && pos.linep->s[0] == NUL)
X return &pos;
X
X if (dec(&pos) == -1)
X return NULL;
X }
X
X sclass = cls(gchar(&pos));
X
X /*
X * Move backward to start of this word.
X */
X while (cls(gchar(&pos)) == sclass) {
X if (dec(&pos) == -1)
X return NULL;
X }
X inc(&pos); /* overshot - forward one */
X
X return &pos;
X}
X
X/*
X * end_word(pos, type) - move to the end of the word
X *
X * There is an apparent bug in the 'e' motion of the real vi. At least on the
X * System V Release 3 version for the 80386. Unlike 'b' and 'w', the 'e'
X * motion crosses blank lines. When the real vi crosses a blank line in an
X * 'e' motion, the cursor is placed on the FIRST character of the next
X * non-blank line. The 'E' command, however, works correctly. Since this
X * appears to be a bug, I have not duplicated it here.
X *
X * Returns the resulting position, or NULL if EOF was reached.
X */
XLPtr *
Xend_word(p, type)
X LPtr *p;
X int type;
X{
X static LPtr pos;
X int sclass = cls(gchar(p)); /* starting class */
X
X S_CHECK_TOPCHAR_AND_BOTCHAR;
X
X pos = *p;
X
X stype = type;
X
X if (inc(&pos) == -1)
X return NULL;
X
X /*
X * If we're in the middle of a word, we just have to move to the end of
X * it.
X */
X if (cls(gchar(&pos)) == sclass && sclass != 0) {
X /*
X * Move forward to end of the current word
X */
X while (cls(gchar(&pos)) == sclass) {
X if (inc(&pos) == -1)
X return NULL;
X }
X dec(&pos); /* overshot - forward one */
X return &pos;
X }
X /*
X * We were at the end of a word. Go to the end of the next word.
X */
X
X while (cls(gchar(&pos)) == 0) { /* skip any white space */
X if (inc(&pos) == -1)
X return NULL;
X }
X
X sclass = cls(gchar(&pos));
X
X /*
X * Move forward to end of this word.
X */
X while (cls(gchar(&pos)) == sclass) {
X if (inc(&pos) == -1)
X return NULL;
X }
X dec(&pos); /* overshot - forward one */
X
X return &pos;
X}
SHAR_EOF
echo "End of archive 5 (of 6)"
# if you want to concatenate archives, remove anything after this line
exit